package com.dsg.token;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.Map;

/**
 * JWT包含了三部分：
 * Header 头部(标题包含了令牌的元数据，并且包含签名和/或加密算法的类型)
 * JWT的头部承载两部分信息：token类型和采用的加密算法。
 * {
 * "alg": "HS256",
 * "typ": "JWT"
 * }
 * Payload 负载 (类似于飞机上承载的物品)
 * Signature 签名/签证
 */
public class JavaWebToken {

    /**
     * 根据用户名、ID生成加密的token
     *
     * @param userName
     * @param userId
     * @return
     */
    public static String generateUserToken(String userName, String userId) {
        //过期时间
        Date currentDate = new Date();
        Date expireDate = new Date(currentDate.getTime() + JWTUtil.TOKEN_EXPIRE_TIME);
        //私钥及加密算法
        Algorithm algorithm = Algorithm.HMAC256(JWTUtil.TOKEN_SECRET_KEY);
        //设置头部信息
        Map<String, Object> headerMap = Maps.newHashMap();
        headerMap.put("typ", "JWT");
        headerMap.put("alg", "HS256");
        //附带username和id生成token
        String token = JWT.create()
                .withHeader(headerMap)
                .withClaim("iss", IDUtil.ID_PREFIX)// jwt签发者
                .withClaim("userId", userId)//自定义信息
                .withClaim("userName", userName)//自定义信息
                .withIssuedAt(currentDate)//发行日期
                .withExpiresAt(expireDate)//发行过期日期
                .sign(algorithm);//加密算法
        return token;
    }

    /**
     * 解密Token
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static Map<String, Claim> verifyToken(String token) {
        Map<String, Claim> jwtMap = Maps.newHashMap();
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(JWTUtil.TOKEN_SECRET_KEY)).build();
            DecodedJWT jwt = verifier.verify(token);
            jwtMap = jwt.getClaims();
        } catch (Exception e) {
            System.out.println("Token过期或者不存在,请重新登录");
        }
        return jwtMap;
    }

    /**
     * 根据Token获取userId
     *
     * @param token
     * @return userId
     */
    public static String getUserIdByToken(String token) {
        Map<String, Claim> claims = verifyToken(token);
        Claim userIdClaim = claims.get("userId");
        if (null == userIdClaim || StringUtils.isEmpty(userIdClaim.asString())) {
            // token 校验失败, 抛出Token验证非法异常
            return "error";
        }
        System.out.println("Token校验成功!");
        return userIdClaim.asString();
    }

    public static void main(String[] args) throws Exception {
        String token = generateUserToken("blue", "TestPWD123");
        System.out.println("原始Token==>\n" + token);
        String userId = getUserIdByToken(token);
        System.out.println(userId);
    }

}
